﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Web;
using Mindfor.Web.Data;
using System.Web.Mvc;

namespace Mindfor.Web
{
	/// <summary>
	/// Specifies the minimum and maximum length of characters that are allowed in a data field.
	/// Data is validated only when specified module option value matches.
	/// </summary>
	public class RegularExpressionWhenModuleOption : RegularExpressionAttribute, IClientValidatable
	{
		/// <summary>
		/// Gets or sets module option name.
		/// </summary>
		public string OptionName { get; set; }

		/// <summary>
		/// Gets or sets value to match option to.
		/// </summary>
		public object Value { get; set; }

		/// <summary>
		/// Initializes new instance.
		/// </summary>
		/// <param name="maximumLength">The maximum length of a string.</param>
		/// <param name="optionName">Module option name.</param>
		/// <param name="value">Value to match option to.</param>
		public RegularExpressionWhenModuleOption(string regexPattern, string optionName, object value)
			: base(regexPattern)
		{
			OptionName = optionName;
			Value = value;
		}

		/// <summary>
		/// Determines whether a specified object is valid.
		/// </summary>
		/// <param name="value">The object to validate.</param>
		/// <param name="validationContext">The context information about the validation operation.</param>
		/// <returns>An instance of the System.ComponentModel.DataAnnotations.ValidationResult class.</returns>
		protected override ValidationResult IsValid(object value, ValidationContext validationContext)
		{
			if (IsOptionMatches())
				return base.IsValid(value, validationContext);
			return ValidationResult.Success;
		}

		/// <summary>
		/// When implemented in a class, returns client validation rules for that class.
		/// </summary>
		/// <param name="metadata">The model metadata.</param>
		/// <param name="context">The controller context.</param>
		/// <returns>The client validation rules for this validator.</returns>
		public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
		{
			if (IsOptionMatches())
			{
				return new ModelClientValidationRegexRule[]
				{
					new ModelClientValidationRegexRule(ErrorMessage, Pattern)
				};
			}
			return new ModelClientValidationRule[0];
		}

		/// <summary>
		/// Returns true, if option value matches. Otherwise false.
		/// </summary>
		protected bool IsOptionMatches()
		{
			if (HttpContext.Current != null)
			{
				ModuleBase module = HttpContext.Current.Items["module"] as ModuleBase;
				if (module != null)
				{
					ModuleOption option = module.Options[OptionName];
					if (option != null)
					{
						object optionValue = option.GetValue();
						return optionValue == null && Value == null || Value != null && Value.Equals(optionValue);
					}
				}
			}

			return false;
		}
	}
}
